package com.tanx.cqrs.infrastructure.spring.event.store;

import com.tanx.cqrs.event.Event;
import com.tanx.cqrs.event.store.EventRepository;
import com.tanx.cqrs.event.store.EventStoreRepository;
import org.springframework.context.ApplicationContext;
import org.springframework.core.ResolvableType;
import org.springframework.util.StringUtils;

import java.util.Collection;

/**
 * 获取事件存储库
 */
public class EventStoreRepositoryFactory {

    private ApplicationContext context;

    public EventStoreRepositoryFactory(ApplicationContext context) {
        this.context = context;
    }

    /**
     * 根据聚合类型查找聚合的事件存储仓库
     * 1,首先根据聚合上的注解查找bean中的repository
     * 2,根据聚合的类型,查找在bean中是否存在repository<T>的聚合
     *
     * @param aggregate 聚合类型
     * @param <T>       聚合class类型
     * @return 聚合仓库
     */
    @SuppressWarnings("unchecked")
    public <T, E extends Event> EventStoreRepository<T, E> getStoreRepository(Class<T> aggregate) {
        EventRepository annotation = aggregate.getAnnotation(EventRepository.class);
        if (annotation != null && !StringUtils.isEmpty(annotation.beanName())) {
            return context.getBean(annotation.beanName(), EventStoreRepository.class);
        }
        //查找泛型bean
        Collection<EventStoreRepository> beans = context.getBeansOfType(EventStoreRepository.class).values();
        if (beans != null && beans.size() == 1) {
            for (EventStoreRepository bean : beans) {
                return bean;
            }
        }
        if (beans != null && !beans.isEmpty()) {
            for (EventStoreRepository bean : beans) {
                ResolvableType resolvableType = ResolvableType.forClass(bean.getClass());
                for (ResolvableType type : resolvableType.getInterfaces()) {
                    ResolvableType[] generics = type.getGenerics();
                    if (!type.isAssignableFrom(EventStoreRepository.class)) {
                        continue;
                    }
                    for (ResolvableType generic : generics) {
//                        if (generic.isAssignableFrom(aggregate)) {
//                            return bean;
//                        }
                        if (aggregate.getClass().equals(generic.resolve())) {
                            return bean;
                        }
                    }
                }
            }
        }
        throw new RuntimeException("未找到" + aggregate.getSimpleName() + "的EventStoreRepository");
    }
}
